﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace Utils
{
    /// <summary>
    /// 加密辅助类
    /// </summary>
    public class EncryptHelper
    {
        #region 常量定义

        /// <summary>
        /// 默认的盐值2
        /// </summary>
        public static readonly string SALT2 = "WONGOING";
        /// <summary>
        /// 默认加密次数
        /// </summary>
        public static readonly int HASHITERATIONS = 1024;
        /// <summary>
        /// MD5加密算法
        /// </summary>
        public static readonly string ALGORITHM_MD5 = "MD5";
        /// <summary>
        /// SHA-1加密算法
        /// </summary>
        public static readonly string ALGORITHM_SHA1 = "SHA-1";
        /// <summary>
        /// SHA-256加密算法
        /// </summary>
        public static readonly string ALGORITHM_SHA256 = "SHA-256";
        /// <summary>
        /// SHA-512加密算法
        /// </summary>
        public static readonly string ALGORITHM_SHA512 = "SHA-512";

        #endregion

        #region 方法定义

        /// <summary>
        /// 加密方法
        /// </summary>
        /// <param name="source">要加密的原文， 通常传入密码明文</param>
        /// <param name="algorithmName">要使用的加密算法，如MD5、SHA-1、SHA-256、SHA-512</param>
        /// <param name="salt1">盐值1，盐的生成可以使用Guid.NewGuid().ToString()，也可以使用RNGCryptoServiceProvider 类</param>
        /// <param name="salt2">盐值2</param>
        /// <param name="hashIterations">要加密的次数</param>
        /// <returns>返回加密后的密文</returns>
        public static String Encrypt(string source, string algorithmName, string salt1, string salt2 = "", int hashIterations = 1)
        {
            if (null == source) source = "";
            if (null == algorithmName) algorithmName = "MD5";
            if (null == salt1) salt1 = "";
            if (null == salt2) salt2 = "";
            string result = String.Empty;
            if (algorithmName == ALGORITHM_MD5)
            {
                result = MD5Encrypt(source, salt1, salt2, hashIterations);
            }
            else if (algorithmName == ALGORITHM_SHA1)
            {
                result = SHA1Encrypt(source, salt1, salt2, hashIterations);
            }
            else if (algorithmName == ALGORITHM_SHA256)
            {
                result = SHA256Encrypt(source, salt1, salt2, hashIterations);
            }
            else if (algorithmName == ALGORITHM_SHA512)
            {
                result = SHA512Encrypt(source, salt1, salt2, hashIterations);
            }
            return result;
        }

        /// <summary>
        /// MD5加密方法
        /// </summary>
        /// <param name="source">要加密的原文， 通常传入密码明文</param>
        /// <param name="salt1">盐值1</param>
        /// <param name="salt2">盐值2</param>
        /// <param name="hashIterations">要加密的次数</param>
        /// <returns>返回加密后的密文</returns>
        public static string MD5Encrypt(string source, string salt1, string salt2, int hashIterations)
        {
            byte[] saltPasswordValue = UTF8Encoding.UTF8.GetBytes(salt1 + salt2 + source);
            MD5 md5 = MD5.Create();
            saltPasswordValue = md5.ComputeHash(saltPasswordValue);
            for (int i = 0; i < hashIterations - 1; i++)
            {
                saltPasswordValue = md5.ComputeHash(saltPasswordValue);
            }
            md5.Dispose();
            string result = BitConverter.ToString(saltPasswordValue);
            result = result.Replace("-", String.Empty).ToLower();
            return result;
        }

        /// <summary>
        /// SHA1加密方法
        /// </summary>
        /// <param name="source">要加密的原文， 通常传入密码明文</param>
        /// <param name="salt1">盐值1</param>
        /// <param name="salt2">盐值2</param>
        /// <param name="hashIterations">要加密的次数</param>
        /// <returns>返回加密后的密文</returns>
        public static string SHA1Encrypt(string source, string salt1, string salt2, int hashIterations)
        {
            byte[] saltPasswordValue = UTF8Encoding.UTF8.GetBytes(salt1 + salt2 + source);
            SHA1 sha1 = SHA1.Create();
            saltPasswordValue = sha1.ComputeHash(saltPasswordValue);
            for (int i = 0; i < hashIterations - 1; i++)
            {
                saltPasswordValue = sha1.ComputeHash(saltPasswordValue);
            }
            sha1.Dispose();
            string result = BitConverter.ToString(saltPasswordValue);
            result = result.Replace("-", String.Empty).ToLower();
            return result;
        }

        /// <summary>
        /// SHA256加密方法
        /// </summary>
        /// <param name="source">要加密的原文， 通常传入密码明文</param>
        /// <param name="salt1">盐值1</param>
        /// <param name="salt2">盐值2</param>
        /// <param name="hashIterations">要加密的次数</param>
        /// <returns>返回加密后的密文</returns>
        public static string SHA256Encrypt(string source, string salt1, string salt2, int hashIterations)
        {
            byte[] saltPasswordValue = UTF8Encoding.UTF8.GetBytes(salt1 + salt2 + source);
            SHA256 sha256 = SHA256.Create();
            saltPasswordValue = sha256.ComputeHash(saltPasswordValue);
            for (int i = 0; i < hashIterations - 1; i++)
            {
                saltPasswordValue = sha256.ComputeHash(saltPasswordValue);
            }
            sha256.Dispose();
            string result = BitConverter.ToString(saltPasswordValue);
            result = result.Replace("-", String.Empty).ToLower();
            return result;
        }

        /// <summary>
        /// SHA512加密方法
        /// </summary>
        /// <param name="source">要加密的原文， 通常传入密码明文</param>
        /// <param name="salt1">盐值1</param>
        /// <param name="salt2">盐值2</param>
        /// <param name="hashIterations">要加密的次数</param>
        /// <returns>返回加密后的密文</returns>
        public static string SHA512Encrypt(string source, string salt1, string salt2, int hashIterations)
        {
            byte[] saltPasswordValue = UTF8Encoding.UTF8.GetBytes(salt1 + salt2 + source);
            SHA512 sha512 = SHA512.Create();
            saltPasswordValue = sha512.ComputeHash(saltPasswordValue);
            for (int i = 0; i < hashIterations - 1; i++)
            {
                saltPasswordValue = sha512.ComputeHash(saltPasswordValue);
            }
            sha512.Dispose();
            string result = BitConverter.ToString(saltPasswordValue);
            result = result.Replace("-", String.Empty).ToLower();
            return result;
        }

        #endregion
    }
}
